Activities and Exchanges

This notebook shows how to use the Activity and Exchange classes.

In [1]:
from brightway2 import *

Let's create a new project just for this notebook

In [2]:
projects.current = "cats and dogs"

Let's start with a new database:

In [3]:
db = Database("a&e")

and insert some basic data:

In [4]:
db.write({
    ("a&e", "cat"): {
        'name': 'cat',
        'unit': 'kilogram',
        'color': 'black',  # Custom field - you can add whatever fields you need
        'exchanges': [{
            'input': ('a&e', 'cat food'),
            'amount': 10,
            'type': 'technosphere'
        }, {
            'input': ('a&e', 'kitty litter'),
            'amount': 10,
            'type': 'technosphere'            
        }, {
            'input': ('a&e', 'smell'),
            'amount': 1,
            'type': 'biosphere'            
        }]
    },
    ("a&e", "kitty litter"): {'name': 'yuck'},
    ("a&e", "cat food"): {'name': 'yum'},
    ("a&e", "smell"): {'name': 'stinky', 'type': 'biosphere'},
})
Writing activities to SQLite3 database:
0%  100%
[####] | ETA[sec]: 0.000 
Total time elapsed: 0.022 sec
Title: Writing activities to SQLite3 database:
  Started: 05/16/2015 00:27:47
  Finished: 05/16/2015 00:27:47
  Total time elapsed: 0.022 sec
  CPU %: 116.400000
  Memory %: 0.734663

We can get an activity with .get():

In [5]:
act = db.get("cat")
act
Out[5]:
'cat' (kilogram, None, None)

The cat process has no categories or location so far. Let's change that:

In [6]:
act['location'] = 'inside'
act['categories'] = ['felis', 'catus']
act
Out[6]:
'cat' (kilogram, inside, ['felis', 'catus'])

When we are ready, we can save our changes:

In [7]:
act.save()

We can iterate over the available data fields:

In [8]:
for key in act:
    print(key, ':', act[key])
code : cat
unit : kilogram
database : a&e
name : cat
categories : ['felis', 'catus']
color : black
location : inside

Note that the fields database and code are added automatically for us.

There are only a few methods for an activity. We can see the activity key (combination of database and code):

In [9]:
act.key
Out[9]:
('a&e', 'cat')

In the database, this is stored as a single text field with a special character splitting the two:

In [10]:
act.dbkey
Out[10]:
'a&e⊡cat'

We can iterate over all exchanges:

In [11]:
for exc in act.exchanges():
    print(exc)
Exchange: 10 None 'yum' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
Exchange: 10 None 'yuck' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
Exchange: 1 None 'stinky' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>

Or just the technosphere/biosphere/production exchanges:

In [12]:
print("technosphere:")
for exc in act.exchanges():
    print(exc)
print("biosphere:")
for exc in act.biosphere():
    print(exc)
print("production:")
for exc in act.production():
    print(exc)
technosphere:
Exchange: 10 None 'yum' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
Exchange: 10 None 'yuck' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
Exchange: 1 None 'stinky' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
biosphere:
Exchange: 1 None 'stinky' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
production:

You can also count exchanges (or any of the specific types of exchanges):

In [13]:
len(act.exchanges())
Out[13]:
3

There weren't any production exchanges. Brightway2 will add a default production exchanges with amount of 1 when building the technosphere matrix if no production exchange is given.

We can also look at upstream exchanges - those that consume this activity's reference product. We don't have any yet, so let's create a new activity:

In [14]:
na = db.new_activity("dog")
na.save()
---------------------------------------------------------------------------
ValidityError                             Traceback (most recent call last)
<ipython-input-14-1ce2ba0be795> in <module>()
      1 na = db.new_activity("dog")
----> 2 na.save()

/Users/cmutel/local34/bw3dev/lib/python3.4/site-packages/bw2data/backends/peewee/proxies.py in save(self)
     72             raise ValidityError("This activity can't be saved for the "
     73                 "following reasons\n\t* " + \
---> 74                 "\n\t* ".join(self.valid(why=True)[1])
     75             )
     76 

ValidityError: This activity can't be saved for the following reasons
	* Missing field ``name``

Oops, activities must have names. Let's fix that:

In [15]:
na['name'] = 'fido'
na.save()

We will also get a nice error message for invalid new exchanges:

In [16]:
na.new_exchange().save()
---------------------------------------------------------------------------
ValidityError                             Traceback (most recent call last)
<ipython-input-16-514e23f89f03> in <module>()
----> 1 na.new_exchange().save()

/Users/cmutel/local34/bw3dev/lib/python3.4/site-packages/bw2data/backends/peewee/proxies.py in save(self)
    162             raise ValidityError("This exchange can't be saved for the "
    163                 "following reasons\n\t* " + \
--> 164                 "\n\t* ".join(self.valid(why=True)[1])
    165             )
    166 

ValidityError: This exchange can't be saved for the following reasons
	* Missing field ``input``
	* Invalid or missing field ``amount``
	* Missing field ``type``

Let's add a link to our cat process. Don't worry, the dog won't really eat the cat!

In [17]:
new_exc = na.new_exchange(input=act, amount=1, type='technosphere')
new_exc.save()

We can now see that 'fido' links to 'cat':

In [18]:
for exc in na.technosphere():
    print(exc)
for exc in act.upstream():
    print(exc)
Exchange: 1 kilogram 'cat' (kilogram, inside, ['felis', 'catus']) to 'fido' (None, GLO, None)>
Exchange: 1 kilogram 'cat' (kilogram, inside, ['felis', 'catus']) to 'fido' (None, GLO, None)>

exc.input and exc.output will return activities:

In [19]:
new_exc.input, new_exc.output
Out[19]:
('cat' (kilogram, inside, ['felis', 'catus']), 'fido' (None, GLO, None))

Exchanges have a few more methods:

In [20]:
new_exc.unit, new_exc.amount, new_exc.uncertainty_type
Out[20]:
('kilogram', 1, stats_arrays.distributions.undefined.UndefinedUncertainty)

Let's add some uncertainty to this exchange (see http://stats-arrays.readthedocs.org/en/latest/):

In [21]:
from stats_arrays import NormalUncertainty

new_exc['uncertainty type'] = NormalUncertainty.id
new_exc['loc'], new_exc['scale'] = 1, 0.25
new_exc.save()

We can now get an uncertainty dictionary for use in stats_arrays functions:

In [22]:
new_exc.uncertainty
Out[22]:
{'loc': 1, 'scale': 0.25, 'uncertainty type': 3}

And can get a random sample:

In [23]:
new_exc.random_sample(n=10)
Out[23]:
array([ 0.83300474,  0.71212005,  1.08467909,  0.73926401,  1.00244101,
        0.90949908,  0.86061365,  0.82956251,  0.81421195,  0.85891137])

We can copy activities. This will copy the activities exchanges:

In [24]:
kudu = act.copy(name="kudu", code='antelope')
kudu
Out[24]:
'kudu' (kilogram, inside, ['felis', 'catus'])
In [25]:
for exc in kudu.exchanges():
    print(exc)
Exchange: 10 None 'yum' (None, None, None) to 'kudu' (kilogram, inside, ['felis', 'catus'])>
Exchange: 10 None 'yuck' (None, None, None) to 'kudu' (kilogram, inside, ['felis', 'catus'])>
Exchange: 1 None 'stinky' (None, None, None) to 'kudu' (kilogram, inside, ['felis', 'catus'])>

Upstream exchanges are (of course) not copied:

In [26]:
for exc in kudu.upstream():
    print(exc)

You can delete the some or all of an activities exchanges:

In [27]:
print("Before:",len(kudu.exchanges()))
kudu.biosphere().delete()
print("After:", len(kudu.exchanges()))
Before: 3
After: 2

You can also delete activities:

In [28]:
kudu.delete()

Our new activity is no longer in the database:

In [30]:
kudu in db
Out[30]:
False
In [ ]: